package com.corpgovernment.permission.config;

import com.corpgovernment.api.permission.DataPermissionType;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.ResourceInfo;
import com.corpgovernment.permission.service.RoleResourceService;
import com.corpgovernment.redis.cache.RoleResourceManager;
import com.ctrip.corp.obt.generic.core.context.RequestContext;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.exception.CommonException;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.shard.context.PermissionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author marco.zheng
 * @version 1.0
 * @date 2021/05/06
 * @desc Page filter
 * @see
 * @since 1.0
 */
@Slf4j
@Component
@WebFilter(filterName = "permissionFilter", urlPatterns = "/*")
public class PermissionFilter implements Filter {

    public static final String DATA_PERMISSION_ORG_ID_LIST="dataPermissionOrgIds";
    public static final String DATA_PERMISSION_CORP_ID_LIST="dataPermissionCorpIds";

    @Autowired
    private RoleResourceManager manager;
    @Autowired
    private RoleResourceService roleResourceService;

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 本地测试
/*        Map<String,String> ctx = new HashMap<>();
        ctx.put("dataPermissionLevel","1");
        ctx.put("roleId","444");
        UserInfoContext.putAllContextParams(ctx);*/
        Object dataPermissionControl = UserInfoContext.getContextParams("dataPermissionLevel");
        Object roleId = UserInfoContext.getContextParams("roleId");
        Object permissionKeyObj = UserInfoContext.getContextParams("permission-key");
        Object noPermission = UserInfoContext.getContextParams("noPermission");

        log.info("dataPermissionControl:{},roleId:{},permissionKeyObj:{},noPermission:{}", dataPermissionControl, roleId, permissionKeyObj, noPermission);

        if (Objects.nonNull(noPermission) && "true".equals(noPermission.toString())) {
            log.info("数据权限拦截器校验不通过，无数据权限");
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter writer = response.getWriter();
            writer.write("{\"msg\":\"无数据权限\",\"status\":200}");
            return;
        }
        if (Objects.isNull(dataPermissionControl) || Objects.isNull(roleId) || Objects.isNull(permissionKeyObj)) {
            log.info("数据权限拦截器放行，dataPermissionControl:{},roleId:{}，permissionKeyObj:{}", dataPermissionControl, roleId, permissionKeyObj);
            chain.doFilter(request, response);
            return;
        }

        Integer dataPermission = Integer.valueOf(dataPermissionControl.toString());
        String permissionKey = permissionKeyObj.toString();
        ResourceInfo resource =
                manager.getResource(UserInfoContext.getContextParams("roleId").toString(), ResourceInfo.class);

        log.info("数据权限 dataPermission:{},resource:{},permissionKey:{}", dataPermission, JsonUtils.toJsonString(resource), permissionKey);

        if (Objects.isNull(resource) || CollectionUtils.isEmpty(resource.getDeptInfos()) || CollectionUtils.isEmpty(resource.getPermissionInfos())) {
            //调用下游服务获取角色资源数据
            /*BaseUserInfo baseUserInfo = new BaseUserInfo();
            baseUserInfo.setRoleId((Long) roleId);*/
            ResourceInfo resourceData = roleResourceService.getResourceData((Long)roleId);
            //JSONResult<ResourceInfo> userResourceData = permissionClient.findUserResourceData(baseUserInfo);
            manager.setResource(String.valueOf(roleId), resourceData);
            resource = resourceData;
            log.info("数据权限 resource:{}",JsonUtils.toJsonString(resource));
        }
        List<ResourceInfo.DeptInfo> deptInfos=null;
        if(resource!=null) {
            deptInfos = resource.getDeptInfos();
        }

        //如果数据权限状态为OFF未开启，则不走数据权限管控

        //如果数据权限状态为RELATION，则关联公司或部门不能为空，auth-server已经拦截掉
        if (DataPermissionType.RELATION.getLevel().equals(dataPermission)) {
            if (CollectionUtils.isEmpty(deptInfos)) {
                log.info("数据权限校验失败,数据权限级别为RELATION，关联的公司或部门为空，请检查auth-server为什么会放行");
                throw new CommonException("数据权限校验失败!");
            }

            if (deptInfos.stream().anyMatch(i -> Objects.equals("C", i.getOrgType()))) {
                List<String> corpIds = deptInfos.stream().filter(a -> Objects.equals(a.getOrgType(), "C"))
                        .map(ResourceInfo.DeptInfo::getOrgId).collect(Collectors.toList());
                PermissionContext.setCorpIds(corpIds);
            } else {
                List<String> orgIds =
                        deptInfos.stream().map(ResourceInfo.DeptInfo::getOrgId).collect(Collectors.toList());
                PermissionContext.setOrgIds(orgIds);
            }

            setDataPermissionOrgIdAndCorpId(deptInfos);
        }
        if (DataPermissionType.COMPANY_LEVEL.getLevel().equals(dataPermission) || DataPermissionType.GROUP_LEVEL.getLevel().equals(dataPermission)) {
            if (CollectionUtils.isEmpty(deptInfos) || !deptInfos.stream().anyMatch(i -> Objects.equals("C", i.getOrgType()))) {
                log.info("数据权限校验失败,数据权限级别为{}，关联的公司为空，请检查auth-server为什么会放行,deptInfos:{}", dataPermission, JsonUtils.toJsonString(deptInfos));
                throw new CommonException("数据权限校验失败!");
            }

            List<String> corpIds = deptInfos.stream().filter(a -> Objects.equals(a.getOrgType(), "C"))
                    .map(ResourceInfo.DeptInfo::getOrgId).collect(Collectors.toList());
            PermissionContext.setCorpIds(corpIds);

            setDataPermissionOrgIdAndCorpId(deptInfos);
        }

        log.info("数据权限过滤结果：deptInfos:{},dataPermission:{},corpId:{},orgId:{}", JsonUtils.toJsonString(deptInfos), dataPermission, JsonUtils.toJsonString(PermissionContext.getCorpIds()), JsonUtils.toJsonString(PermissionContext.getOrgIds()));

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }

    private void setDataPermissionOrgIdAndCorpId(List<ResourceInfo.DeptInfo> deptInfos){
        if(CollectionUtils.isNotEmpty(deptInfos)){
            List<String> corpIds = deptInfos.stream().filter(a -> Objects.equals(a.getOrgType(), "C"))
                    .map(ResourceInfo.DeptInfo::getOrgId).collect(Collectors.toList());
            List<String> orgIds = deptInfos.stream().map(ResourceInfo.DeptInfo::getOrgId).collect(Collectors.toList());

            if(CollectionUtils.isNotEmpty(orgIds)) {
                RequestContext.getCurrentContext().addContextParams(DATA_PERMISSION_ORG_ID_LIST, orgIds);
            }
            if(CollectionUtils.isNotEmpty(corpIds)) {
                RequestContext.getCurrentContext().addContextParams(DATA_PERMISSION_CORP_ID_LIST, corpIds);
            }

            log.info("数据权限 requestContext orgIds:{},corpIds:{}",JsonUtils.toJsonString(orgIds),JsonUtils.toJsonString(corpIds));
        }
    }
}
